Introdução

Exploratory data analysis on data from RottenTomatoes about actor Jake Gyllenhaal. The code used to mine the data here analyzed and the explanation on how to use it can be found on this report’s repository deste relatório.

  • Entries that have no infomation about box office were ignored.




Data Overview

import_data("jake_gyllenhaal") 
filmes <- read_imported_data()
filmes %>% 
    glimpse()
Observations: 20
Variables: 5
$ avaliacao  <int> 92, 67, 72, 52, 73, 59, 82, 85, 92, 49, 35, 64, 47, 90, 87, 61, 62, 44, 82, 86
$ filme      <chr> "Stronger", "Life", "Nocturnal Animals", "Demolition", "Everest", "Southpaw", "Prisoners", "End of Watch", "Sour...
$ papel      <chr> "Jeff Bauman", "David Jordan", "Tony HastingsEdward Sheffield", "Davis Mitchell", "Scott Fischer", "Billy \"The ...
$ bilheteria <dbl> 4.2, 30.2, 10.7, 1.7, 46.6, 42.4, 61.0, 39.1, 54.7, 33.3, 90.8, 28.6, 9.7, 33.0, 83.0, 62.6, 7.5, 186.6, 13.8, 4.2
$ ano        <int> 2017, 2017, 2016, 2016, 2015, 2015, 2013, 2012, 2011, 2010, 2010, 2009, 2007, 2007, 2005, 2005, 2005, 2004, 2002...

Box Office

  • Data refers to revenue collected inside the USA.
p <- filmes %>%
    ggplot(aes(x = ano, 
               y = bilheteria,
               text = paste("Movie:",filme,
                            "\nBox Office:",
                            bilheteria,"m",
                            "\nYear:",ano))) + 
    geom_point(size = 4, color = paleta[1]) +
    labs(y = "Box Office (MM)", x = "Year of release")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Among the movies where Jake acted one sets itself apart from others in terms of revenue: The movie “The Day After Tomorrow” released in 2004.

  • It’s possible to notice a downward trend in the Box Office of the movies where Jake acted after 2013.

filmes %>% 
    ggplot(aes(x = bilheteria)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = "grey", color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,200,20)) +
    labs(y = "Relative Frequency", x = "Box Office (MM)")

  • We see a clear disparity between “The Day After Tomorrow” and the rest of the movies.

  • No values outside expected domain, e.g. negative values.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = bilheteria,
               label = filme,
               text = paste("Movie:",filme,
                            "\nBox Office:",
                            bilheteria,"m"))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Box Office (MM)")
ggplotly(p, tooltip="text") %>% 
    layout(autosize = F)
  • Separate movies in those whose Box Office is below 50 millions and those whose Box Office is above that seems a reasonable approach.

  • “The Day After Tomorrow” seems to form a group of its own. Which would give us 3 groups.

Rating

p <- filmes %>% 
    ggplot(aes(x = ano, 
               y = avaliacao,
                text = paste("Movie:",filme,
                            "\nRating:",
                            avaliacao,
                            "\nYear:",ano))) + 
    geom_point(size = 4, color = paleta[1])  +
    scale_y_continuous(limits = c(0, 100)) +
    labs(y = "Rating RT", x = "Year of Release")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Between 2005 and 2010 Jake participated in a particular series of movies that did not please the critics.
  • There doesn’t seem to exist a particularly clear tendency in the year of release.
filmes %>% 
    ggplot(aes(x = avaliacao)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = paleta[3], color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,100,10)) +
    labs(y = "Relative Frequency", x = "Rating RT")

  • It’s possible to notice a considerable number of movies with ratings above 80.

  • No values outside expected domain, e.g. negative values.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = avaliacao,
               text = paste(
                    "Filme:",filme,
                    "\nAvaliação:",avaliacao))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Avaliação RT")
ggplotly(p, tooltip = "text") %>% 
    layout(autosize = F)
  • Intuitively three groups arise:
    • The movies with ratings above 80
    • The movies with ratings between 55 and 70
    • The movies with ratings below 55




Hierarchical Clustering



One dimension


Box Office

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (bil=", bilheteria, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(bilheteria) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "centroid")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilarity", x = "", title = "Dendrogram") +
    geom_hline(aes(yintercept = c(20,30), color=c("4 grupos","3 grupos"))) +
    scale_colour_manual(name="#Groups",
    values=c("#56B4E9", "#FF9999"))

  • In terms of Dendogram the separation in four and three groups seems apropriate, given that the increase in dissimilarity from 4 to 3 groups doesn’t seem to be substantial.
  • Cut made for 4 groups
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Movies", y = bilheteria, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Box Office (MM)", x = "", title = "Grouping by Box Office") +
    guides(color=guide_legend(title="group"))

  • The division in 4 groups seems more appropriate than the division in 3 groups.
    • The movie cluster on the base of chart seems to require its own group (In the 4 groups division the aforementioned group would be the group 1).
k_escolhido = 4
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, bilheteria),
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Movie:", reorder(label, bilheteria),
                    "\nRating:", bilheteria,
                    "\nGroup:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Rating RT") + 
    guides(color=guide_legend(title="group")) +
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • The Day After Tomorrow demanded a group for itself, as expected.


Rating

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (av=", avaliacao, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(avaliacao) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "ward.D")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilarity", x = "", title = "Dendrogram") +
    geom_hline(aes(yintercept = 30),color="red")

  • In terms of Dendogram the division in three groups seems the most appropriate, given that the increase in dissimilarity becomes substantial when we go from 3 to 2 groups.
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Movies", y = avaliacao, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") +
    guides(color=guide_legend(title="group")) +
    labs(y = "Rating RT", x = "", title = "Grouping by Rating")

  • Visually the division in three groups seems appropriate in accordance with the dendogram.
k_escolhido = 3
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, avaliacao),
               y = avaliacao,
               colour = grupo,
               text = paste(
                    "Movie:", reorder(label, avaliacao),
                    "\nRating:", avaliacao,
                    "\nGroup:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Rating RT") + 
    guides(color=guide_legend(title="group")) +
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • Arguably, Prince of Persia: The Sands of Time could demand a group of its own.


Two dimensions


Quantos grupos devemos escolher?


agrupamento_h_2d = filmes %>%
   mutate(bilheteria = log10(bilheteria)) %>%
   mutate_at(vars("avaliacao", "bilheteria"), funs(scale)) %>%
   column_to_rownames("filme") %>%
   select("avaliacao", "bilheteria") %>%
   dist(method = "euclidean") %>%
   hclust(method = "ward.D")
ggdendrogram(agrupamento_h_2d, rotate = TRUE, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma") +
    geom_hline(aes(yintercept = 4),color="red")

  • Passar de 4 para 3 grupos representa pouca variação em termos de dissimilaridade
  • Passar de 3 para 2 grupos apresenta um aumento relativo de dissimilaridade substancial, portanto de 6 até 3 grupos parece ser uma boa escolha em termos de dendrograma.
filmes2 <- filmes %>%
    mutate(bilheteria = log10(bilheteria))
plota_hclusts_2d(agrupamento_h_2d,
                filmes2,
                c("avaliacao", "bilheteria"),
                linkage_method = "ward.D", 
                ks = 1:6,
                palette = "Dark2") + 
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação", title = "Agrupamento com Duas Dimensões")

  • A escolha por 5 grupos parece ser apropriada, por refletir tanto questões de bilheteria como de avaliação. Optaremos por 5 grupos pelas seguintes razões (Grupos mencionados no agrupamento de 5 grupos):
    • Os \(\color{magenta}{\text{4 filmes de melhores avaliações}}\) estão bem próximos uns dos outros e sugerem um grupo.
    • Os \(\color{#7C3F7C}{\text{3 filmes de baixas bilheterias e baixas avaliações}}\) estão bem distantes do resto dos filmes e sugerem um grupo.
    • Os \(\color{#16A085}{\text{4 filmes de baixa bilheteria e boas avaliações}}\) estão bem próximos uns dos outros e sugerem um grupo.
    • Os \(\color{green}{\text{2 filmes de altíssima bilheteria e baixíssima avaliação}}\) estão bem distantes do resto dos filmes e sugerem um grupo.
    • Os \(\color{#CF5300}{\text{6 filmes centrais/medianos em termos de bilheteria/avaliação}}\) estão bem próximos uns dos outros e sugerem um grupo.
atribuicoes = get_grupos(agrupamento_h_2d, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    filter(k == 5) %>%
    mutate(filme = label) %>% 
    left_join(filmes, by = "filme")
p <- atribuicoes %>%
    ggplot(aes(x = avaliacao,
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Filme:", filme,
                    "\nBilheteria:", bilheteria,"m\n",
                    "Avaliação:", avaliacao))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação RT")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)




Quais os nomes dos grupos?


\(\color{#16A085}{\text{Grupo 1 (Oddball):}}\) Filmes em geral bem recebidos pela crítica porém mal recebidos pelo público, o que se reflete no seu baixo arrecadamento. O nome Oddball parte do interese de pessoas que se consideram excêntricas em buscarem filmes nesse perfil para revalidarem o sentimento de exclusividade.


\(\color{#CF5300}{\text{Grupo 2 (Sessão da Tarde):}}\) Filmes em geral não tão bem recebidos pela crítica e mais formulaicos. Em termos de bilheteria a maior parte deles foi baixa mas o filme se pagou.O nome Sessã da Tarde parte da ideia de que filmes mais formulaicos e inexpressivos em termos de bilheteria como os do grupo povoarem esse horário da tv brasileira.


\(\color{#7C3F7C}{\text{Grupo 3 (Demolition of a budget):}}\) Filmes em geral mal recebidos pela crítica e pelo público, o que se reflete no seu baixo arrecadamento e avaliações. O nome do grupo parte do baxissimo rendimento dos filmes em termos financeiros, a “demolição” do dinheiro investido na produção do filme.


\(\color{magenta}{\text{Grupo 4 (Broke Records and Awards):}}\) Filmes aclamados pela crítica e de faturamento decente ou de sucesso, os filmes desse grupo são de tom mais sério tratando de assuntos significativos e geradores de controvérsia (assassinatos em série verídicos, não heterossexualidade, terrorismo.. ). O nome do grupo é um trocadilho com o nome de um dos filmes e a quantidade exorbitante de prêmios que esse filme ganhou.


\(\color{green}{\text{Grupo 5 (BlockBusters):}}\) Filmes em que Jack atuou que os críticos não gostaram lá muito mas que excederam em bilheteria, com uma arrecadação girando na casa da centena de milhões de dólares. O termo BlockBuster é usualmente dado a filmes que lotam as salas de cinema, que é o caso dos filmes pertencentes a esse grupo.




Filme-exemplo de cada grupo


\(\color{#16A085}{\text{Grupo 1 (Oddball):}}\)

  • Stronger: Filme biográfico sobre ‘Jeff Bauman’, vítima do atentado de Boston que perdeu ambas as pernas na explosão. O filme foi muito bem recebido pelos críticos que o elogiaram por ser bem executado, comovente e por focar numa história de superação ao invés de usar a tragédia para alimentar a paranóia em cima do terrorismo. O filme porém foi um fracasso em termos de bilheteria.


\(\color{#CF5300}{\text{Grupo 2 (Sessão da Tarde):}}\)

  • Life: Filme no gênero ficção científica espacial, teve um arrecadamento não muito expressivo assim como críticas igualmente pouco entusiasmadas. Foi considerado por muitos bem executados porém pouco inovativo.


\(\color{#7C3F7C}{\text{Grupo 3 (Demolition of a budget):}}\)

  • Demolition: Neste filme Jake atua no papel de um homem que volta ao trabalho depois de perder a esposa e encontra contato humano em uma atendente de telemarketing ao reclamar de uma vending machine. O filme foi um fracasso em termos de arrecadamento assim como em termos de crítica. O filme teve seu script apontado como grande problema, esse foi descrito como ‘tentando afetar profundidade’ e anti-carismático.


\(\color{magenta}{\text{Grupo 4 (Broke Records and Awards):}}\)

  • Brokeback Mountain: Provavelmente a melhor atuação de Jake Gyllenhaal até o momento, esse filme rendeu a Jake uma indicação ao Oscar e levantou muita controvérsia por conter uma cena de sexo entre pessoas do mesmo sexo. A Academia (responsável por escolher os vencedores do Oscar) foi acusada de homofobia por não escolher esse filme como o ganhador de Melhor Fotografia, ainda assim Brokeback Mountain ganhou outros 141 prêmios e 128 nominações de acordo com o IMDB. O filme foi considerado um sucesso tanto em faturamento como em avaliação.


\(\color{green}{\text{Grupo 5 (BlockBusters):}}\)

  • Prince of Persia: The Sands of Time: Baseado no jogo de mesmo nome, jogo que ainda é pra muitos uma referência em qualidade e inovação. O filme resultou em comentários decepcionados tanto de críticos e fãs, os quais curiosamente não falharam em contribuir pro arrecadamento do filme.
LS0tCnRpdGxlOiAiSmFrZSBHeWxsZW5oYWFsJ3MgdHlwZSBvZiBtb3ZpZXMiCmF1dGhvcjogIkpvc8OpIEJlbmFyZGkgZGUgU291emEgTnVuZXMiCmRhdGU6ICIyMi8wNS8yMDE4IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCjxici8+PGJyLz4KCiMgSW50cm9kdcOnw6NvCgo+IEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgb24gZGF0YSBmcm9tIFtSb3R0ZW5Ub21hdG9lc10oaHR0cHM6Ly93d3cucm90dGVudG9tYXRvZXMuY29tLykgYWJvdXQgYWN0b3IgSmFrZSBHeWxsZW5oYWFsLiBUaGUgY29kZSB1c2VkIHRvIG1pbmUgdGhlIGRhdGEgaGVyZSBhbmFseXplZCBhbmQgdGhlIGV4cGxhbmF0aW9uIG9uIGhvdyB0byB1c2UgaXQgY2FuIGJlIGZvdW5kIG9uIFt0aGlzIHJlcG9ydCdzIHJlcG9zaXRvcnldKGh0dHBzOi8vZ2l0aHViLmNvbS9CZW5hcmRpL2FncnVwYW1lbnRvLWZpbG1lcy8pIGRlc3RlIHJlbGF0w7NyaW8uCgoqIEVudHJpZXMgdGhhdCBoYXZlIG5vIGluZm9tYXRpb24gYWJvdXQgYm94IG9mZmljZSB3ZXJlIGlnbm9yZWQuCgo8YnI+CgoqKioKCjxicj4KCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ2dkZW5kcm8pCgpzb3VyY2UoaGVyZTo6aGVyZSgiY29kZS9saWIuUiIpKQpzb3VyY2UoaGVyZTo6aGVyZSgiY29kZS9wbG90YV9zb2x1Y29lc19oY2x1c3QuUiIpKQoKdGhlbWVfc2V0KHRoZW1lX3JlcG9ydCgpKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KHRpZHkgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDYsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gNSwKICAgICAgICAgICAgICAgICAgICAgIGVjaG8gPSBUUlVFKQpwYWxldGEgPSBjKCIjNDA0RTREIiwKICAgICAgICAgICAiIzkyRENFNSIsCiAgICAgICAgICAgIiM5MzhCQTEiLAogICAgICAgICAgICIjMkQzMTQyIiwKICAgICAgICAgICAiI0Y0NzQzQiIpCnNldC5zZWVkKDEwMSkKYGBgCgojIERhdGEgT3ZlcnZpZXcKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmltcG9ydF9kYXRhKCJqYWtlX2d5bGxlbmhhYWwiKSAKZmlsbWVzIDwtIHJlYWRfaW1wb3J0ZWRfZGF0YSgpCmZpbG1lcyAlPiUgCiAgICBnbGltcHNlKCkKYGBgCgojIyBCb3ggT2ZmaWNlCgoqIERhdGEgcmVmZXJzIHRvIHJldmVudWUgY29sbGVjdGVkIGluc2lkZSB0aGUgVVNBLgoKYGBge3J9CnAgPC0gZmlsbWVzICU+JQogICAgZ2dwbG90KGFlcyh4ID0gYW5vLCAKICAgICAgICAgICAgICAgeSA9IGJpbGhldGVyaWEsCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTW92aWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkJveCBPZmZpY2U6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpbGhldGVyaWEsIm0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuWWVhcjoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICsKICAgIGxhYnMoeSA9ICJCb3ggT2ZmaWNlIChNTSkiLCB4ID0gIlllYXIgb2YgcmVsZWFzZSIpCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAoKKiBBbW9uZyB0aGUgbW92aWVzIHdoZXJlIEpha2UgYWN0ZWQgb25lIHNldHMgaXRzZWxmIGFwYXJ0IGZyb20gb3RoZXJzIGluIHRlcm1zIG9mIHJldmVudWU6IFRoZSBtb3ZpZSAqKiJUaGUgRGF5IEFmdGVyIFRvbW9ycm93IioqIHJlbGVhc2VkIGluIDIwMDQuCgoqIEl0J3MgcG9zc2libGUgdG8gbm90aWNlIGEgZG93bndhcmQgdHJlbmQgaW4gdGhlIEJveCBPZmZpY2Ugb2YgdGhlIG1vdmllcyB3aGVyZSBKYWtlIGFjdGVkIGFmdGVyIDIwMTMuICAKCmBgYHtyfQpmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYmlsaGV0ZXJpYSkpICsgCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksYmlud2lkdGggPSAxMCwgYm91bmRhcnkgPSAwLCAKICAgICAgICAgICAgICAgICAgIGZpbGwgPSAiZ3JleSIsIGNvbG9yID0gImJsYWNrIikgKyAKICAgIGdlb21fcnVnKHNpemUgPSAuNSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwyMDAsMjApKSArCiAgICBsYWJzKHkgPSAiUmVsYXRpdmUgRnJlcXVlbmN5IiwgeCA9ICJCb3ggT2ZmaWNlIChNTSkiKQpgYGAKCiogV2Ugc2VlIGEgY2xlYXIgZGlzcGFyaXR5IGJldHdlZW4gKioiVGhlIERheSBBZnRlciBUb21vcnJvdyIqKiBhbmQgdGhlIHJlc3Qgb2YgdGhlIG1vdmllcy4KCiogTm8gdmFsdWVzIG91dHNpZGUgZXhwZWN0ZWQgZG9tYWluLCBlLmcuIG5lZ2F0aXZlIHZhbHVlcy4KCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiIiwKICAgICAgICAgICAgICAgeSA9IGJpbGhldGVyaWEsCiAgICAgICAgICAgICAgIGxhYmVsID0gZmlsbWUsCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTW92aWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkJveCBPZmZpY2U6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpbGhldGVyaWEsIm0iKSkpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wNSwgYWxwaGEgPSAuMywgc2l6ZSA9IDMpICsgCiAgICBsYWJzKHggPSAiIiwgeT0iQm94IE9mZmljZSAoTU0pIikKCmdncGxvdGx5KHAsIHRvb2x0aXA9InRleHQiKSAlPiUgCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogU2VwYXJhdGUgbW92aWVzIGluIHRob3NlIHdob3NlIEJveCBPZmZpY2UgaXMgYmVsb3cgNTAgbWlsbGlvbnMgYW5kIHRob3NlIHdob3NlIEJveCBPZmZpY2UgaXMgYWJvdmUgdGhhdCBzZWVtcyBhIHJlYXNvbmFibGUgYXBwcm9hY2guIAoKKiAqKiJUaGUgRGF5IEFmdGVyIFRvbW9ycm93IioqIHNlZW1zIHRvIGZvcm0gYSBncm91cCBvZiBpdHMgb3duLiBXaGljaCB3b3VsZCBnaXZlIHVzIDMgZ3JvdXBzLgoKIyMgUmF0aW5nCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYW5vLCAKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTW92aWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcblJhdGluZzoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZhbGlhY2FvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuWWVhcjoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArCiAgICBsYWJzKHkgPSAiUmF0aW5nIFJUIiwgeCA9ICJZZWFyIG9mIFJlbGVhc2UiKQoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogQmV0d2VlbiAyMDA1IGFuZCAyMDEwIEpha2UgcGFydGljaXBhdGVkIGluIGEgcGFydGljdWxhciBzZXJpZXMgb2YgbW92aWVzIHRoYXQgZGlkIG5vdCBwbGVhc2UgdGhlIGNyaXRpY3MuIAoqIFRoZXJlIGRvZXNuJ3Qgc2VlbSB0byBleGlzdCBhIHBhcnRpY3VsYXJseSBjbGVhciB0ZW5kZW5jeSBpbiB0aGUgeWVhciBvZiByZWxlYXNlLiAKCmBgYHtyfQpmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYXZhbGlhY2FvKSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PSguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSxiaW53aWR0aCA9IDEwLCBib3VuZGFyeSA9IDAsIAogICAgICAgICAgICAgICAgICAgZmlsbCA9IHBhbGV0YVszXSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgZ2VvbV9ydWcoc2l6ZSA9IC41KSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEwMCwxMCkpICsKICAgIGxhYnMoeSA9ICJSZWxhdGl2ZSBGcmVxdWVuY3kiLCB4ID0gIlJhdGluZyBSVCIpCmBgYAoKKiBJdCdzIHBvc3NpYmxlIHRvIG5vdGljZSBhIGNvbnNpZGVyYWJsZSBudW1iZXIgb2YgbW92aWVzIHdpdGggcmF0aW5ncyBhYm92ZSA4MC4KCiogTm8gdmFsdWVzIG91dHNpZGUgZXhwZWN0ZWQgZG9tYWluLCBlLmcuIG5lZ2F0aXZlIHZhbHVlcy4KCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiIiwKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJGaWxtZToiLGZpbG1lLAogICAgICAgICAgICAgICAgICAgICJcbkF2YWxpYcOnw6NvOiIsYXZhbGlhY2FvKSkpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wNSwgYWxwaGEgPSAuMywgc2l6ZSA9IDMpICsgCiAgICBsYWJzKHggPSAiIiwgeT0iQXZhbGlhw6fDo28gUlQiKQoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogICAgbGF5b3V0KGF1dG9zaXplID0gRikKCmBgYAoKKiBJbnR1aXRpdmVseSB0aHJlZSBncm91cHMgYXJpc2U6CiAgICAqIFRoZSBtb3ZpZXMgd2l0aCByYXRpbmdzIGFib3ZlIDgwCiAgICAqIFRoZSBtb3ZpZXMgd2l0aCByYXRpbmdzIGJldHdlZW4gNTUgYW5kIDcwIAogICAgKiBUaGUgbW92aWVzIHdpdGggcmF0aW5ncyBiZWxvdyA1NQoKPGJyPgoKKioqCgo8YnI+CgojIEhpZXJhcmNoaWNhbCBDbHVzdGVyaW5nCgo8YnI+Cjxicj4KCiMjIE9uZSBkaW1lbnNpb24KCjxicj4KCiMjIyBCb3ggT2ZmaWNlCgpgYGB7cn0KYWdydXBhbWVudG9faCA9IGZpbG1lcyAlPiUgCiAgICBtdXRhdGUobm9tZSA9IHBhc3RlMChmaWxtZSwgIiAoYmlsPSIsIGJpbGhldGVyaWEsICIpIikpICU+JSAKICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICBjb2x1bW5fdG9fcm93bmFtZXMoImZpbG1lIikgJT4lIAogICAgc2VsZWN0KGJpbGhldGVyaWEpICU+JQogICAgZGlzdChtZXRob2QgPSAiZXVjbGlkaWFuIikgJT4lIAogICAgaGNsdXN0KG1ldGhvZCA9ICJjZW50cm9pZCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faCwgcm90YXRlID0gVCwgc2l6ZSA9IDIsIHRoZW1lX2RlbmRybyA9IEYpICsKICAgIGxhYnMoeSA9ICJEaXNzaW1pbGFyaXR5IiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtIikgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IGMoMjAsMzApLCBjb2xvcj1jKCI0IGdydXBvcyIsIjMgZ3J1cG9zIikpKSArCiAgICBzY2FsZV9jb2xvdXJfbWFudWFsKG5hbWU9IiNHcm91cHMiLAogICAgdmFsdWVzPWMoIiM1NkI0RTkiLCAiI0ZGOTk5OSIpKQpgYGAKCiogSW4gdGVybXMgb2YgRGVuZG9ncmFtIHRoZSBzZXBhcmF0aW9uIGluIGZvdXIgYW5kIHRocmVlIGdyb3VwcyBzZWVtcyBhcHJvcHJpYXRlLCBnaXZlbiB0aGF0IHRoZSBpbmNyZWFzZSBpbiBkaXNzaW1pbGFyaXR5IGZyb20gNCB0byAzIGdyb3VwcyBkb2Vzbid0IHNlZW0gdG8gYmUgc3Vic3RhbnRpYWwuCiogQ3V0IG1hZGUgZm9yIDQgZ3JvdXBzCgpgYGB7cn0KYXRyaWJ1aWNvZXMgPSBnZXRfZ3J1cG9zKGFncnVwYW1lbnRvX2gsIG51bV9ncnVwb3MgPSAxOjYpCgphdHJpYnVpY29lcyA9IGF0cmlidWljb2VzICU+JSAKICAgIGxlZnRfam9pbihmaWxtZXMsIGJ5ID0gYygibGFiZWwiID0gImZpbG1lIikpCgphdHJpYnVpY29lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiTW92aWVzIiwgeSA9IGJpbGhldGVyaWEsIGNvbG91ciA9IGdydXBvKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMS42LCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3JvdXBzIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICAgIGxhYnMoeSA9ICJCb3ggT2ZmaWNlIChNTSkiLCB4ID0gIiIsIHRpdGxlID0gIkdyb3VwaW5nIGJ5IEJveCBPZmZpY2UiKSArCiAgICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKHRpdGxlPSJncm91cCIpKQpgYGAKCiogVGhlIGRpdmlzaW9uIGluIDQgZ3JvdXBzIHNlZW1zIG1vcmUgYXBwcm9wcmlhdGUgdGhhbiB0aGUgZGl2aXNpb24gaW4gMyBncm91cHMuCiAgICAqIFRoZSBtb3ZpZSBjbHVzdGVyIG9uIHRoZSBiYXNlIG9mIGNoYXJ0IHNlZW1zIHRvIHJlcXVpcmUgaXRzIG93biBncm91cCAoSW4gdGhlIDQgZ3JvdXBzIGRpdmlzaW9uIHRoZSBhZm9yZW1lbnRpb25lZCBncm91cCB3b3VsZCBiZSB0aGUgZ3JvdXAgMSkuCgpgYGB7cn0Ka19lc2NvbGhpZG8gPSA0CgptIDwtIGxpc3QobCA9IDIyMCkKCnAgPC1hdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSBrX2VzY29saGlkbykgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihsYWJlbCwgYmlsaGV0ZXJpYSksCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICBjb2xvdXIgPSBncnVwbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJNb3ZpZToiLCByZW9yZGVyKGxhYmVsLCBiaWxoZXRlcmlhKSwKICAgICAgICAgICAgICAgICAgICAiXG5SYXRpbmc6IiwgYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgICAgICAiXG5Hcm91cDoiLCBncnVwbykpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDIsIGhlaWdodCA9IDAsIHNpemUgPSAzLCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3JvdXBzIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsgCiAgICBsYWJzKHggPSAiIiwgeSA9ICJSYXRpbmcgUlQiKSArIAogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iZ3JvdXAiKSkgKwogICAgY29vcmRfZmxpcCgpCgpnZ3Bsb3RseShwLHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRiwgbWFyZ2luID0gbSkKCmBgYAoKKiAqKlRoZSBEYXkgQWZ0ZXIgVG9tb3Jyb3cqKiBkZW1hbmRlZCBhIGdyb3VwIGZvciBpdHNlbGYsIGFzIGV4cGVjdGVkLgoKPGJyPgoKIyMjIFJhdGluZyAKCmBgYHtyfQphZ3J1cGFtZW50b19oID0gZmlsbWVzICU+JSAKICAgIG11dGF0ZShub21lID0gcGFzdGUwKGZpbG1lLCAiIChhdj0iLCBhdmFsaWFjYW8sICIpIikpICU+JSAKICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICBjb2x1bW5fdG9fcm93bmFtZXMoImZpbG1lIikgJT4lIAogICAgc2VsZWN0KGF2YWxpYWNhbykgJT4lCiAgICBkaXN0KG1ldGhvZCA9ICJldWNsaWRpYW4iKSAlPiUgCiAgICBoY2x1c3QobWV0aG9kID0gIndhcmQuRCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faCwgcm90YXRlID0gVCwgc2l6ZSA9IDIsIHRoZW1lX2RlbmRybyA9IEYpICsKICAgIGxhYnMoeSA9ICJEaXNzaW1pbGFyaXR5IiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtIikgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDMwKSxjb2xvcj0icmVkIikKYGBgCgoqIEluIHRlcm1zIG9mIERlbmRvZ3JhbSB0aGUgKipkaXZpc2lvbiBpbiB0aHJlZSBncm91cHMgc2VlbXMgdGhlIG1vc3QgYXBwcm9wcmlhdGUqKiwgZ2l2ZW4gdGhhdCB0aGUgaW5jcmVhc2UgaW4gZGlzc2ltaWxhcml0eSBiZWNvbWVzIHN1YnN0YW50aWFsIHdoZW4gd2UgZ28gZnJvbSAzIHRvIDIgZ3JvdXBzLgoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9IGMoImxhYmVsIiA9ICJmaWxtZSIpKQoKYXRyaWJ1aWNvZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIk1vdmllcyIsIHkgPSBhdmFsaWFjYW8sIGNvbG91ciA9IGdydXBvKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMS42LCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3JvdXBzIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9Imdyb3VwIikpICsKICAgIGxhYnMoeSA9ICJSYXRpbmcgUlQiLCB4ID0gIiIsIHRpdGxlID0gIkdyb3VwaW5nIGJ5IFJhdGluZyIpCgpgYGAKCiogVmlzdWFsbHkgdGhlIGRpdmlzaW9uIGluIHRocmVlIGdyb3VwcyBzZWVtcyBhcHByb3ByaWF0ZSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIGRlbmRvZ3JhbS4KCmBgYHtyfQprX2VzY29saGlkbyA9IDMKCm0gPC0gbGlzdChsID0gMjIwKQoKcCA8LWF0cmlidWljb2VzICU+JSAKICAgIGZpbHRlcihrID09IGtfZXNjb2xoaWRvKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGxhYmVsLCBhdmFsaWFjYW8pLAogICAgICAgICAgICAgICB5ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICBjb2xvdXIgPSBncnVwbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJNb3ZpZToiLCByZW9yZGVyKGxhYmVsLCBhdmFsaWFjYW8pLAogICAgICAgICAgICAgICAgICAgICJcblJhdGluZzoiLCBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICAgICAgIlxuR3JvdXA6IiwgZ3J1cG8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdyb3VwcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgbGFicyh4ID0gIiIsIHkgPSAiUmF0aW5nIFJUIikgKyAKICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9Imdyb3VwIikpICsKICAgIGNvb3JkX2ZsaXAoKQoKZ2dwbG90bHkocCx0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYsIG1hcmdpbiA9IG0pCgpgYGAKCiogQXJndWFibHksICoqUHJpbmNlIG9mIFBlcnNpYTogVGhlIFNhbmRzIG9mIFRpbWUqKiBjb3VsZCBkZW1hbmQgYSBncm91cCBvZiBpdHMgb3duLgoKPGJyPgoKIyMgVHdvIGRpbWVuc2lvbnMKCjxicj4KCiMjIyBRdWFudG9zIGdydXBvcyBkZXZlbW9zIGVzY29saGVyPyAKCjxicj4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQphZ3J1cGFtZW50b19oXzJkID0gZmlsbWVzICU+JQogICBtdXRhdGUoYmlsaGV0ZXJpYSA9IGxvZzEwKGJpbGhldGVyaWEpKSAlPiUKICAgbXV0YXRlX2F0KHZhcnMoImF2YWxpYWNhbyIsICJiaWxoZXRlcmlhIiksIGZ1bnMoc2NhbGUpKSAlPiUKICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JQogICBzZWxlY3QoImF2YWxpYWNhbyIsICJiaWxoZXRlcmlhIikgJT4lCiAgIGRpc3QobWV0aG9kID0gImV1Y2xpZGVhbiIpICU+JQogICBoY2x1c3QobWV0aG9kID0gIndhcmQuRCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faF8yZCwgcm90YXRlID0gVFJVRSwgdGhlbWVfZGVuZHJvID0gRikgKwogICAgbGFicyh5ID0gIkRpc3NpbWlsYXJpZGFkZSIsIHggPSAiIiwgdGl0bGUgPSAiRGVuZHJvZ3JhbWEiKSArCiAgICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gNCksY29sb3I9InJlZCIpCgpgYGAKCiogUGFzc2FyIGRlIDQgcGFyYSAzIGdydXBvcyByZXByZXNlbnRhIHBvdWNhIHZhcmlhw6fDo28gZW0gdGVybW9zIGRlIGRpc3NpbWlsYXJpZGFkZQoqIFBhc3NhciBkZSAzIHBhcmEgMiBncnVwb3MgYXByZXNlbnRhIHVtIGF1bWVudG8gcmVsYXRpdm8gZGUgZGlzc2ltaWxhcmlkYWRlIHN1YnN0YW5jaWFsLCBwb3J0YW50byBkZSA2IGF0w6kgMyBncnVwb3MgcGFyZWNlIHNlciB1bWEgYm9hIGVzY29saGEgZW0gdGVybW9zIGRlIGRlbmRyb2dyYW1hLgoKYGBge3J9CmZpbG1lczIgPC0gZmlsbWVzICU+JQogICAgbXV0YXRlKGJpbGhldGVyaWEgPSBsb2cxMChiaWxoZXRlcmlhKSkKCnBsb3RhX2hjbHVzdHNfMmQoYWdydXBhbWVudG9faF8yZCwKICAgICAgICAgICAgICAgIGZpbG1lczIsCiAgICAgICAgICAgICAgICBjKCJhdmFsaWFjYW8iLCAiYmlsaGV0ZXJpYSIpLAogICAgICAgICAgICAgICAgbGlua2FnZV9tZXRob2QgPSAid2FyZC5EIiwgCiAgICAgICAgICAgICAgICBrcyA9IDE6NiwKICAgICAgICAgICAgICAgIHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnMoeSA9ICJCaWxoZXRlcmlhIiwgeCA9ICJBdmFsaWHDp8OjbyIsIHRpdGxlID0gIkFncnVwYW1lbnRvIGNvbSBEdWFzIERpbWVuc8O1ZXMiKQpgYGAKCiogQSBlc2NvbGhhIHBvciA1IGdydXBvcyBwYXJlY2Ugc2VyIGFwcm9wcmlhZGEsIHBvciByZWZsZXRpciB0YW50byBxdWVzdMO1ZXMgZGUgYmlsaGV0ZXJpYSBjb21vIGRlIGF2YWxpYcOnw6NvLiAqKk9wdGFyZW1vcyBwb3IgNSBncnVwb3MqKiBwZWxhcyBzZWd1aW50ZXMgcmF6w7VlcyAoR3J1cG9zIG1lbmNpb25hZG9zIG5vIGFncnVwYW1lbnRvIGRlIDUgZ3J1cG9zKTogCiAgICAqIE9zICRcY29sb3J7bWFnZW50YX17XHRleHR7NCBmaWxtZXMgZGUgbWVsaG9yZXMgYXZhbGlhw6fDtWVzfX0kIGVzdMOjbyBiZW0gcHLDs3hpbW9zIHVucyBkb3Mgb3V0cm9zIGUgc3VnZXJlbSB1bSBncnVwby4KICAgICogT3MgJFxjb2xvcnsjN0MzRjdDfXtcdGV4dHszIGZpbG1lcyBkZSBiYWl4YXMgYmlsaGV0ZXJpYXMgZSBiYWl4YXMgYXZhbGlhw6fDtWVzfX0kIGVzdMOjbyBiZW0gZGlzdGFudGVzIGRvIHJlc3RvIGRvcyBmaWxtZXMgZSBzdWdlcmVtIHVtIGdydXBvLgogICAgKiBPcyAkXGNvbG9yeyMxNkEwODV9e1x0ZXh0ezQgZmlsbWVzIGRlIGJhaXhhIGJpbGhldGVyaWEgZSBib2FzIGF2YWxpYcOnw7Vlc319JCBlc3TDo28gYmVtIHByw7N4aW1vcyB1bnMgZG9zIG91dHJvcyBlIHN1Z2VyZW0gdW0gZ3J1cG8uCiAgICAqIE9zICRcY29sb3J7Z3JlZW59e1x0ZXh0ezIgZmlsbWVzIGRlIGFsdMOtc3NpbWEgYmlsaGV0ZXJpYSBlIGJhaXjDrXNzaW1hIGF2YWxpYcOnw6NvfX0kIGVzdMOjbyBiZW0gZGlzdGFudGVzIGRvIHJlc3RvIGRvcyBmaWxtZXMgZSBzdWdlcmVtIHVtIGdydXBvLgogICAgKiBPcyAkXGNvbG9yeyNDRjUzMDB9e1x0ZXh0ezYgZmlsbWVzIGNlbnRyYWlzL21lZGlhbm9zIGVtIHRlcm1vcyBkZSBiaWxoZXRlcmlhL2F2YWxpYcOnw6NvfX0kIGVzdMOjbyBiZW0gcHLDs3hpbW9zIHVucyBkb3Mgb3V0cm9zIGUgc3VnZXJlbSB1bSBncnVwby4KICAgIAogICAgCgpgYGB7cn0KYXRyaWJ1aWNvZXMgPSBnZXRfZ3J1cG9zKGFncnVwYW1lbnRvX2hfMmQsIG51bV9ncnVwb3MgPSAxOjYpCgphdHJpYnVpY29lcyA9IGF0cmlidWljb2VzICU+JSAKICAgIGZpbHRlcihrID09IDUpICU+JQogICAgbXV0YXRlKGZpbG1lID0gbGFiZWwpICU+JSAKICAgIGxlZnRfam9pbihmaWxtZXMsIGJ5ID0gImZpbG1lIikKCnAgPC0gYXRyaWJ1aWNvZXMgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICBjb2xvdXIgPSBncnVwbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJGaWxtZToiLCBmaWxtZSwKICAgICAgICAgICAgICAgICAgICAiXG5CaWxoZXRlcmlhOiIsIGJpbGhldGVyaWEsIm1cbiIsCiAgICAgICAgICAgICAgICAgICAgIkF2YWxpYcOnw6NvOiIsIGF2YWxpYWNhbykpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDIsIGhlaWdodCA9IDAsIHNpemUgPSAzLCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3J1cG9zIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSIsIHggPSAiQXZhbGlhw6fDo28gUlQiKQoKCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRikKYGBgCgo8YnI+CgoqKioKCjxicj4KCiMjIyBRdWFpcyBvcyBub21lcyBkb3MgZ3J1cG9zPyAKCjxicj4KCiRcY29sb3J7IzE2QTA4NX17XHRleHR7R3J1cG8gMSAoT2RkYmFsbCk6fX0kIEZpbG1lcyBlbSBnZXJhbCBfYmVtIHJlY2ViaWRvcyBwZWxhIGNyw610aWNhIHBvcsOpbSBtYWwgcmVjZWJpZG9zIHBlbG8gcMO6YmxpY29fLCBvIHF1ZSBzZSByZWZsZXRlIG5vIHNldSBiYWl4byBhcnJlY2FkYW1lbnRvLiBPIG5vbWUgT2RkYmFsbCBwYXJ0ZSBkbyBpbnRlcmVzZSBkZSBwZXNzb2FzIHF1ZSBzZSBjb25zaWRlcmFtIGV4Y8OqbnRyaWNhcyBlbSBidXNjYXJlbSBmaWxtZXMgbmVzc2UgcGVyZmlsIHBhcmEgcmV2YWxpZGFyZW0gbyBzZW50aW1lbnRvIGRlIGV4Y2x1c2l2aWRhZGUuCgo8YnIvPgoKJFxjb2xvcnsjQ0Y1MzAwfXtcdGV4dHtHcnVwbyAyIChTZXNzw6NvIGRhIFRhcmRlKTp9fSQgRmlsbWVzIGVtIGdlcmFsIF9uw6NvIHTDo28gYmVtIHJlY2ViaWRvcyBwZWxhIGNyw610aWNhIGUgbWFpcyBmb3JtdWxhaWNvc18uIEVtIHRlcm1vcyBkZSBiaWxoZXRlcmlhIGEgbWFpb3IgcGFydGUgZGVsZXMgZm9pIGJhaXhhIG1hcyBvIGZpbG1lIHNlIHBhZ291Lk8gbm9tZSBTZXNzw6MgZGEgVGFyZGUgcGFydGUgZGEgaWRlaWEgZGUgcXVlIGZpbG1lcyBtYWlzIGZvcm11bGFpY29zIGUgaW5leHByZXNzaXZvcyBlbSB0ZXJtb3MgZGUgYmlsaGV0ZXJpYSBjb21vIG9zIGRvIGdydXBvIHBvdm9hcmVtIGVzc2UgaG9yw6FyaW8gZGEgdHYgYnJhc2lsZWlyYS4KCjxici8+CgokXGNvbG9yeyM3QzNGN0N9e1x0ZXh0e0dydXBvIDMgKERlbW9saXRpb24gb2YgYSBidWRnZXQpOn19JCBGaWxtZXMgZW0gZ2VyYWwgX21hbCByZWNlYmlkb3MgcGVsYSBjcsOtdGljYSBlIHBlbG8gcMO6YmxpY29fLCBvIHF1ZSBzZSByZWZsZXRlIG5vIHNldSBiYWl4byBhcnJlY2FkYW1lbnRvIGUgYXZhbGlhw6fDtWVzLiBPIG5vbWUgZG8gZ3J1cG8gcGFydGUgZG8gYmF4aXNzaW1vIHJlbmRpbWVudG8gZG9zIGZpbG1lcyBlbSB0ZXJtb3MgZmluYW5jZWlyb3MsIGEgImRlbW9sacOnw6NvIiBkbyBkaW5oZWlybyBpbnZlc3RpZG8gbmEgcHJvZHXDp8OjbyBkbyBmaWxtZS4gCgo8YnIvPgoKJFxjb2xvcnttYWdlbnRhfXtcdGV4dHtHcnVwbyA0IChCcm9rZSBSZWNvcmRzIGFuZCBBd2FyZHMpOn19JCBGaWxtZXMgX2FjbGFtYWRvcyBwZWxhIGNyw610aWNhXyBlIGRlIGZhdHVyYW1lbnRvIGRlY2VudGUgb3UgZGUgIHN1Y2Vzc28sIG9zIGZpbG1lcyBkZXNzZSBncnVwbyBzw6NvIGRlIHRvbSBtYWlzIHPDqXJpbyB0cmF0YW5kbyBkZSBhc3N1bnRvcyBzaWduaWZpY2F0aXZvcyBlIGdlcmFkb3JlcyBkZSBjb250cm92w6lyc2lhIChhc3Nhc3NpbmF0b3MgZW0gc8OpcmllIHZlcsOtZGljb3MsIG7Do28gaGV0ZXJvc3NleHVhbGlkYWRlLCB0ZXJyb3Jpc21vLi4gKS4gTyBub21lIGRvIGdydXBvIMOpIHVtIHRyb2NhZGlsaG8gY29tIG8gbm9tZSBkZSB1bSBkb3MgZmlsbWVzIGUgYSBxdWFudGlkYWRlIGV4b3JiaXRhbnRlIGRlIHByw6ptaW9zIHF1ZSBlc3NlIGZpbG1lIGdhbmhvdS4gCgo8YnIvPgoKJFxjb2xvcntncmVlbn17XHRleHR7R3J1cG8gNSAoQmxvY2tCdXN0ZXJzKTp9fSQgRmlsbWVzIGVtIHF1ZSBKYWNrIGF0dW91IHF1ZSBvcyBjcsOtdGljb3MgbsOjbyBnb3N0YXJhbSBsw6EgbXVpdG8gbWFzIHF1ZSBleGNlZGVyYW0gZW0gYmlsaGV0ZXJpYSwgY29tIHVtYSBhcnJlY2FkYcOnw6NvIGdpcmFuZG8gbmEgY2FzYSBkYSBjZW50ZW5hIGRlIG1pbGjDtWVzIGRlIGTDs2xhcmVzLiBPIHRlcm1vIEJsb2NrQnVzdGVyIMOpIHVzdWFsbWVudGUgZGFkbyBhIGZpbG1lcyBxdWUgbG90YW0gYXMgc2FsYXMgZGUgY2luZW1hLCBxdWUgw6kgbyBjYXNvIGRvcyBmaWxtZXMgcGVydGVuY2VudGVzIGEgZXNzZSBncnVwby4KCjxicj4KCioqKgoKPGJyLz4KCiMjIyBGaWxtZS1leGVtcGxvIGRlIGNhZGEgZ3J1cG8gIAoKPGJyLz4KCiRcY29sb3J7IzE2QTA4NX17XHRleHR7R3J1cG8gMSAoT2RkYmFsbCk6fX0kCgoqICoqU3Ryb25nZXIqKjogRmlsbWUgYmlvZ3LDoWZpY28gc29icmUgJ0plZmYgQmF1bWFuJywgdsOtdGltYSBkbyBhdGVudGFkbyBkZSBCb3N0b24gcXVlIHBlcmRldSBhbWJhcyBhcyBwZXJuYXMgbmEgZXhwbG9zw6NvLiBPIGZpbG1lIGZvaSBtdWl0byBiZW0gcmVjZWJpZG8gcGVsb3MgY3LDrXRpY29zIHF1ZSBvIGVsb2dpYXJhbSBwb3Igc2VyIGJlbSBleGVjdXRhZG8sIGNvbW92ZW50ZSBlIHBvciBmb2NhciBudW1hIGhpc3TDs3JpYSBkZSBzdXBlcmHDp8OjbyBhbyBpbnbDqXMgZGUgdXNhciBhIHRyYWfDqWRpYSBwYXJhIGFsaW1lbnRhciBhIHBhcmFuw7NpYSBlbSBjaW1hIGRvIHRlcnJvcmlzbW8uIE8gZmlsbWUgcG9yw6ltIGZvaSB1bSBmcmFjYXNzbyBlbSB0ZXJtb3MgZGUgYmlsaGV0ZXJpYS4KCjxici8+CgokXGNvbG9yeyNDRjUzMDB9e1x0ZXh0e0dydXBvIDIgKFNlc3PDo28gZGEgVGFyZGUpOn19JAoKKiAqKkxpZmUqKjogRmlsbWUgbm8gZ8OqbmVybyBmaWPDp8OjbyBjaWVudMOtZmljYSBlc3BhY2lhbCwgdGV2ZSB1bSBhcnJlY2FkYW1lbnRvIG7Do28gbXVpdG8gZXhwcmVzc2l2bwphc3NpbSBjb21vIGNyw610aWNhcyBpZ3VhbG1lbnRlIHBvdWNvIGVudHVzaWFzbWFkYXMuIEZvaSBjb25zaWRlcmFkbyBwb3IgbXVpdG9zIGJlbSBleGVjdXRhZG9zIHBvcsOpbSBwb3VjbyBpbm92YXRpdm8uCgo8YnIvPgoKJFxjb2xvcnsjN0MzRjdDfXtcdGV4dHtHcnVwbyAzIChEZW1vbGl0aW9uIG9mIGEgYnVkZ2V0KTp9fSQgCgoqICoqRGVtb2xpdGlvbioqOiBOZXN0ZSBmaWxtZSBKYWtlIGF0dWEgbm8gcGFwZWwgZGUgdW0gaG9tZW0gcXVlIHZvbHRhIGFvIHRyYWJhbGhvIGRlcG9pcyBkZSBwZXJkZXIgYSBlc3Bvc2EgZSBlbmNvbnRyYSBjb250YXRvIGh1bWFubyBlbSB1bWEgYXRlbmRlbnRlIGRlIHRlbGVtYXJrZXRpbmcgYW8gcmVjbGFtYXIgZGUgdW1hIHZlbmRpbmcgbWFjaGluZS4gTyBmaWxtZSBmb2kgdW0gZnJhY2Fzc28gZW0gdGVybW9zIGRlIGFycmVjYWRhbWVudG8gYXNzaW0gY29tbyBlbSB0ZXJtb3MgZGUgY3LDrXRpY2EuIE8gZmlsbWUgdGV2ZSBzZXUgc2NyaXB0IGFwb250YWRvIGNvbW8gZ3JhbmRlIHByb2JsZW1hLCBlc3NlIGZvaSBkZXNjcml0byBjb21vICd0ZW50YW5kbyBhZmV0YXIgcHJvZnVuZGlkYWRlJyBlIGFudGktY2FyaXNtw6F0aWNvLgogICAgCjxici8+CgokXGNvbG9ye21hZ2VudGF9e1x0ZXh0e0dydXBvIDQgKEJyb2tlIFJlY29yZHMgYW5kIEF3YXJkcyk6fX0kCgoqICoqQnJva2ViYWNrIE1vdW50YWluKio6IFByb3ZhdmVsbWVudGUgYSBtZWxob3IgYXR1YcOnw6NvIGRlIEpha2UgR3lsbGVuaGFhbCBhdMOpIG8gbW9tZW50bywgZXNzZSBmaWxtZSByZW5kZXUgYSBKYWtlIHVtYSBpbmRpY2HDp8OjbyBhbyBPc2NhciBlIGxldmFudG91IG11aXRhIGNvbnRyb3bDqXJzaWEgcG9yIGNvbnRlciB1bWEgY2VuYSBkZSBzZXhvIGVudHJlIHBlc3NvYXMgZG8gbWVzbW8gc2V4by4gQSBBY2FkZW1pYSAocmVzcG9uc8OhdmVsIHBvciBlc2NvbGhlciBvcyB2ZW5jZWRvcmVzIGRvIE9zY2FyKSBmb2kgYWN1c2FkYSBkZSBob21vZm9iaWEgcG9yIG7Do28gZXNjb2xoZXIgZXNzZSBmaWxtZSBjb21vIG8gZ2FuaGFkb3IgZGUgTWVsaG9yIEZvdG9ncmFmaWEsIGFpbmRhIGFzc2ltIEJyb2tlYmFjayBNb3VudGFpbiBnYW5ob3Ugb3V0cm9zIDE0MSBwcsOqbWlvcyBlIDEyOCBub21pbmHDp8O1ZXMgZGUgYWNvcmRvIGNvbSBvIElNREIuIE8gZmlsbWUgZm9pIGNvbnNpZGVyYWRvIHVtIHN1Y2Vzc28gdGFudG8gZW0gZmF0dXJhbWVudG8gY29tbyBlbSBhdmFsaWHDp8Ojby4KCjxici8+CgokXGNvbG9ye2dyZWVufXtcdGV4dHtHcnVwbyA1IChCbG9ja0J1c3RlcnMpOn19JCAKCiogKipQcmluY2Ugb2YgUGVyc2lhOiBUaGUgU2FuZHMgb2YgVGltZSoqOiBCYXNlYWRvIG5vIGpvZ28gZGUgbWVzbW8gbm9tZSwgam9nbyBxdWUgYWluZGEgw6kgcHJhIG11aXRvcyB1bWEgcmVmZXLDqm5jaWEgZW0gcXVhbGlkYWRlIGUgaW5vdmHDp8Ojby4gTyBmaWxtZSByZXN1bHRvdSBlbSBjb21lbnTDoXJpb3MgZGVjZXBjaW9uYWRvcyB0YW50byBkZSBjcsOtdGljb3MgZSBmw6NzLCBvcyBxdWFpcyBjdXJpb3NhbWVudGUgbsOjbyBmYWxoYXJhbSBlbSBjb250cmlidWlyIHBybyBhcnJlY2FkYW1lbnRvIGRvIGZpbG1lLgogICAgCg==